package api

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"sync"

	h2of "gitee.com/h2ob/h2of/base"
	"github.com/gin-gonic/gin/binding"
)

type httpConnector struct {
	client *http.Client
	mu     sync.Mutex
}

var httpCon *httpConnector
var httpOnce sync.Once

func get() *httpConnector {
	httpOnce.Do(func() {
		// tr := &http.Transport{
		// 	MaxIdleConns:          10,
		// 	MaxConnsPerHost:       50,
		// 	IdleConnTimeout:       30 * time.Second,
		// 	ResponseHeaderTimeout: 0,
		// 	DisableCompression:    true,
		// }
		client := &http.Client{}
		httpCon = &httpConnector{client: client, mu: sync.Mutex{}}
	})
	return httpCon
}

func doPost(url string, reqBody any, out any) error {
	js, err := json.Marshal(reqBody)
	if err != nil {
		h2of.GLogger.Warnf("marshal failed:%s", err.Error())
		return err
	}
	req, err := http.NewRequest("POST", url, bytes.NewReader(js))
	if err != nil {
		h2of.GLogger.Warnf("NewRequest:%s", err.Error())
		return err
	}
	hc := get()
	rsp, err := hc.client.Do(req)
	if err != nil {
		h2of.GLogger.Warnf("Do Request err:%s", err.Error())
		return err
	}
	defer rsp.Body.Close()
	body, err := io.ReadAll(rsp.Body)
	if err != nil {
		h2of.GLogger.Warnf("Read Request err:%s", err.Error())
		return err
	}
	err = binding.JSON.BindBody(body, out)
	if err != nil {
		h2of.GLogger.Warnf("BindBody err:%s", err.Error())
		return err
	}
	return err
}

func doGet(baseUrl string, params map[string]string, header map[string]string) ([]byte, error) {
	bUrl, err := url.Parse(baseUrl)
	if err != nil {
		h2of.GLogger.Infof("parse failed %s\n", err)
		return nil, err
	}
	if params != nil {
		qp := url.Values{}
		for k, v := range params {
			qp.Add(k, v)
		}
		bUrl.RawQuery = qp.Encode()
	}
	rUrl := bUrl.String()
	req, err := http.NewRequest("GET", rUrl, nil)
	if err != nil {
		h2of.GLogger.Warnf("NewRequest:%s", err.Error())
		return nil, err
	}

	for k, v := range header {
		req.Header.Add(k, v)
	}

	hc := get()
	rsp, err := hc.client.Do(req)
	if err != nil {
		h2of.GLogger.Warnf("Do Request err:%s", err.Error())
		return nil, err
	}
	defer rsp.Body.Close()
	body, err := io.ReadAll(rsp.Body)
	if err != nil {
		h2of.GLogger.Warnf("Read Request err:%s", err.Error())
		return nil, err
	}
	return body, nil
}
